import numpy as np


def knn(_x, data, k=3):
    """
    _x 需要预测的数据点
    data [x,y] 数据的x和y
    k 临近值的数量
    先拿预测的值跟所有的x做差,然后求平方,再求和,再开方(求预测点和所有点的距离)
    """
    temp = _x - data[0]
    temp = np.power(temp, 2)
    temp = temp.sum(axis=1)
    temp = np.sqrt(temp)
    # argsort()用法,表示对数据进行从小到大进行排序,返回数据的索引值
    argsort = temp.argsort()
    result = data[1][argsort][:k]
    # bincount就是统计出一个列表的各个元素的出现次数
    # argmax就是求自变量最大值(列表中的最大值)
    return np.bincount(result).argmax()


def load_data():
    """
    读取约会数据
    """
    with open('约会数据.txt') as fp:
        lines = fp.readlines()

    x = np.empty((len(lines), 3), dtype=float)
    y = np.empty((len(lines)), dtype=int)

    for i in range(len(lines)):
        line = lines[i].strip().split('\t')
        x[i] = line[:3]
        y[i] = line[3]
    return x, y


def norm(x):
    """
    数据归一化
    """
    # 这里是按列统计的
    x_col_min = x.min(axis=0)
    x_col_max = x.max(axis=0)
    # 这里处理后最小值是0
    x_norm = x - x_col_min
    # 这里处理后最大值是1
    x_norm /= x_col_max - x_col_min
    return x_norm


x, y = load_data()
x = norm(x)

# 切分数据集
test_x = x[900:]
test_y = y[900:]
x = x[:900]
y = y[:900]

# 测试准确率
correct = 0
for i in range(len(test_x)):
    pred = knn(test_x[i], [x, y], k=5)
    if pred == test_y[i]:
        correct += 1
print(correct / len(test_x))